The programming environment for early operating system was in 16-bit code. However, it was found that 16-bit code did not deal well with large pieces of data and longer complex programs. The later developed 32-bit code was found to be easier to program in and capable of handling larger programs.
Consequently, due to the increasing complexity of programming and performance demands on operating systems, the tendency has been to migrate toward 32-bit code environments for programming and for the operating system components themselves. One problem with this is that large amounts of 16-bit code still exist without suitable 32-bit code replacements, and without any mechanism inherent in the 16-bit code for correctly calling 32-bit code. For example, in IBM's OS/2 operating system environment, some of the most notable remaining 16-bit code is in the extended services, such as database manager, communications manager, and netbios. A significant amount of user and application code also still exists only in the 16-bit format.
In a uniform code environment, a common coding style for service providers such as the database and communications managers is to have the service user register certain callback functions that are to be called whenever particular events occur.
In the ordinary course, the executing program utilises a dynamic portion of storage known as the stack for storing and accessing all of the dynamic data objects required to implement the program. A procedure activation record or stack frame is allocated from the stack for each procedure, and contains all of the variables declared within the procedure, the parameters with which the procedure was called and a return address of the calling procedure.
In the case of 16-bit code, stack storage is arranged in segments not exceeding 64K bytes, and 16-bit code cannot correctly access data that spans a 64K byte segment boundary. A 16-bit pointer is formated to provide the address of a data object by identifying the segment number and the number of bytes that the beginning of the data object is offset from the beginning of the 64K byte segment in which it is found. This form of pointer is often referred to as "segmented".
One problem in accessing 16-bit data objects through a called 32-bit subroutine arises in the difference in pointer format between the two types of code.
The storage environment for 32-bit code can be created in a very large segment (up to 4 gigabytes in size). The pointers identifying the beginning addresses of data objects within this large segment simply indicate the number of bytes offset from the base of this large segment. Because the base linear address for all 32-bit pointers is zero, these pointers are often described as "linear" or "flat". As 32-bit code makes no provision for recognising the limited 64K byte segments of 16-bit memory, it is clear that 32-bit functions cannot access data objects by reference to the values provided in 16-bit pointers.
Therefore, with the advent of operating systems in the 32-bit environment, problems arise when a 32-bit application registers functions with 16-bit subroutines, such as the service providers described above. When the 16-bit code issues a call to a function in 32-bit code, control within program implementation will not be correctly transferred to the 32-bit code, and without capability of allowing 16-bit code to call 32-bit code, the usefulness of a purely 32-bit compiler in mixed code environments is severely restricted.
A further restriction in the use of a 32-bit compiler in the operating system is that the 16-bit code cannot be recompiled without access to the source code for the 16-bit code program or function.
Generalized solutions have been offered to deal with such matters as the problems raised in a situation where access to an extended address space may be required by systems having different word lengths without the basic addressing system reflecting their physical structure (U.S. Pat. No. 4,493,027--Katz), and memory accesses utilizing different data structures (U.S. Pat. Nos. 5,060,186--Barbagelata, and 4,297,743 --Appell).
However, the only solution offered to the present problem of calling from 16-bit code functions to 32-bit code is to provide special assembler "glue" subroutines in 16-bit code for each individual application to perform the "thunk". No automatic solution appears to exist.